/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package controlador;

import clases.Almacen;
import clases.AlmacenArticulo;
import clases.Articulo;
import clases.Categoria;
import java.sql.SQLException;
import java.util.ArrayList;
import modelo.Conexion;
import modelo.MdlAlmacen;
import modelo.MdlAlmacenArticulo;
import modelo.MdlArticulo;

/**
 *
 * @author Edder
 */
public class CtrlArticulo implements Controlador<Articulo> {

    private final MdlArticulo mdlArticulo;
    private final Conexion cnx;

    public CtrlArticulo() {
        this.mdlArticulo = new MdlArticulo();
        this.cnx = Conexion.getConexionDefault();
    }

    /**
     *
     * @param articulo
     * @param cnx
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    @Override
    public void insert(Articulo articulo, Conexion cnx) throws ClassNotFoundException, SQLException {
        if(cnx == null){
            this.cnx.abrirConexion();
            this.cnx.abrirTransaccion();
            this.mdlArticulo.insert(articulo, this.cnx);
            articulo.setIdArticulo(this.mdlArticulo.getLastId(this.cnx));
            this.cnx.cerrarTransaccion();
            this.cnx.cerrarConexion();
        }else{
            this.mdlArticulo.insert(articulo, cnx);
            articulo.setIdArticulo(this.mdlArticulo.getLastId(cnx));
        }            
    }

    /**
     *
     * @param articulo
     * @param cnx
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    @Override
    public void update(Articulo articulo, Conexion cnx) throws ClassNotFoundException, SQLException {
        if(cnx == null){
            this.cnx.abrirConexion();
            this.mdlArticulo.update(articulo, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            this.mdlArticulo.update(articulo, cnx);
        }        
    }
    
    /**
     * Cambia estado de artículo a 'I': Inactivo
     * @param articulo
     * @param cnx
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public void dar_baja(Articulo articulo, Conexion cnx) throws ClassNotFoundException, SQLException {
        if(cnx == null){
            this.cnx.abrirConexion();
            this.mdlArticulo.dar_baja(articulo, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            this.mdlArticulo.update(articulo, cnx);
        }
    }

    /**
     *
     * @param query
     * @param cnx
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public ArrayList<Articulo> getArticulos(String query, Conexion cnx) throws ClassNotFoundException, SQLException {
        ArrayList<Articulo> articulos;
        if(cnx == null){
            this.cnx.abrirConexion();
            articulos = this.mdlArticulo.getArticulos(query, null, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            articulos = this.mdlArticulo.getArticulos(query, null, cnx);
        }
        return articulos;
    }

    /**
     *
     * @param idCategoria
     * @param cnx
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public ArrayList<Articulo> getArticulos_categoria(int idCategoria, Conexion cnx) throws ClassNotFoundException, SQLException {
        ArrayList<Articulo> articulos;
        if(cnx == null){
            this.cnx.abrirConexion();
            articulos = this.mdlArticulo.getArticulos_categoria(idCategoria, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            articulos = this.mdlArticulo.getArticulos_categoria(idCategoria, cnx);
        }
        return articulos;
    }
    
    /**
     *
     * @param query
     * @param inactivo
     * @param cnx
     * @param categorias
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public ArrayList<Articulo> getArticulos_categorias(Conexion cnx, String query, boolean inactivo, 
            ArrayList<Categoria> categorias) throws ClassNotFoundException, SQLException {
        
        ArrayList<Articulo> articulos;
        String where = (inactivo ? "" : " AND estado = 'A' ");
        
        if(!categorias.isEmpty()){
            String strcat = " AND (";
            strcat = categorias.stream().map(
                    (cat) -> "idCategoria = " + cat.getIdCategoria() + " OR "
            ).reduce(strcat, String::concat);

            int size = strcat.length() - 3;
            where += strcat.substring(0, size) + ")";        
        }
            
        if(cnx == null){
            this.cnx.abrirConexion();
            articulos = this.mdlArticulo.getArticulos(query, where, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            articulos = this.mdlArticulo.getArticulos(query, where, cnx);
        }
        return articulos;
    }

    /**
     *Devuelve un arreglo de Object de  3 columnas (idArticulo, nombre, stock)
     * @param idAlmacen
     * @param query
     * @param cnx
     * @return ArrayList<Object[]>
     * @throws SQLException
     * @throws java.lang.ClassNotFoundException
     */
    public ArrayList<Object[]> getArticulosStock_almacen(int idAlmacen, String query, Conexion cnx) throws SQLException, ClassNotFoundException{
        ArrayList<Object[]> articulosStock;
        if(cnx == null){
            this.cnx.abrirConexion();
            articulosStock = this.mdlArticulo.getArticulosStock_almacen(idAlmacen, query, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            articulosStock = this.mdlArticulo.getArticulosStock_almacen(idAlmacen, query, cnx);
        }
        return articulosStock;
    }
    
    /**
     *
     * @param idAlmacen
     * @param cnx
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public ArrayList<Articulo> getArticulos_almacen(int idAlmacen, String busqueda, Conexion cnx) throws ClassNotFoundException, SQLException {
        ArrayList<Articulo> articulos;
        if(cnx == null){
            this.cnx.abrirConexion();
            articulos = this.mdlArticulo.getArticulos_almacen(idAlmacen, busqueda, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            articulos = this.mdlArticulo.getArticulos_almacen(idAlmacen, busqueda, cnx);
        }
        return articulos;
    }

    /**
     *
     * @param idCategoria
     * @param query
     * @param cnx
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public ArrayList<Articulo> getArticulos_categoria(int idCategoria, String query, Conexion cnx) throws ClassNotFoundException, SQLException {
        ArrayList<Articulo> articulos;
        if(cnx == null){
            this.cnx.abrirConexion();
            articulos = this.mdlArticulo.getArticulos_categoria(idCategoria, query, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            articulos = this.mdlArticulo.getArticulos_categoria(idCategoria, query, cnx);
        }
        return articulos;
    }

    /**
     *
     * @param idAlmacen
     * @param query
     * @param cnx
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
//    public ArrayList<Articulo> getArticulos_almacen(int idAlmacen, String query, Conexion cnx) throws ClassNotFoundException, SQLException {
//        ArrayList<Articulo> articulos;
//        if(cnx == null){
//            this.cnx.abrirConexion();
//            articulos = this.mdlArticulo.getArticulos_almacen(idAlmacen, query, this.cnx);
//            this.cnx.cerrarConexion();
//        }else{
//            articulos = this.mdlArticulo.getArticulos_almacen(idAlmacen, query, cnx);
//        }
//        return articulos;
//    }

    /**
     *
     * @param idArticulo
     * @param cnx
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    @Override
    public Articulo get(int idArticulo, Conexion cnx) throws ClassNotFoundException, SQLException {
        Articulo articulo;
        if(cnx == null){
            this.cnx.abrirConexion();
            articulo = this.mdlArticulo.get(idArticulo, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            articulo = this.mdlArticulo.get(idArticulo, cnx);
        }
        return articulo;
    }

    /**
     * Actualiza el stock de un artículo en un almacén
     *
     * @param idAlmacenArticulo
     * @param variacion
     * @param cnx
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public void updateStock(int idAlmacenArticulo, int variacion, Conexion cnx) throws ClassNotFoundException, SQLException {
        MdlAlmacenArticulo mdlAlmacenArticulo = new MdlAlmacenArticulo();
        if(cnx == null){
            this.cnx.abrirConexion();
            mdlAlmacenArticulo.updateStock(idAlmacenArticulo, variacion, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            mdlAlmacenArticulo.updateStock(idAlmacenArticulo, variacion, cnx);
        }
    }

    /**
     * Asigna un artículo a un almacén, stock y stock mínimo en 0
     *
     * @param idArticulo
     * @param idAlmacen
     * @param cnx
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public void asignarAlmacen(int idArticulo, int idAlmacen, Conexion cnx) throws ClassNotFoundException, SQLException {        
        asignarAlmacen(
                new AlmacenArticulo(-1,
                        new Almacen() {
                            {
                                this.setIdAlmacen(idAlmacen);
                            }
                        },
                        new Articulo() {
                            {
                                this.setIdArticulo(idArticulo);
                            }
                        },
                        0,
                        0),
                cnx
        );
    }

    /**
     *
     * @param almacenArticulo
     * @param cnx
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public void asignarAlmacen(AlmacenArticulo almacenArticulo, Conexion cnx) throws ClassNotFoundException, SQLException {        
        MdlAlmacenArticulo mdlAlmacenArticulo = new MdlAlmacenArticulo();
        if(cnx == null){
            this.cnx.abrirConexion();
            mdlAlmacenArticulo.insert(almacenArticulo, this.cnx);
            this.cnx.cerrarConexion();
        }else{
            mdlAlmacenArticulo.insert(almacenArticulo, cnx);
        }
    }

    /**
     *
     * @param idArticulo
     * @param cnx
     * @return
     * @throws SQLException
     * @throws ClassNotFoundException
     */
    public ArrayList<AlmacenArticulo> getStocks(int idArticulo, Conexion cnx ) throws SQLException, ClassNotFoundException {
        MdlAlmacen mdlAlmacen = new MdlAlmacen();
        MdlAlmacenArticulo mdlAlmacenArticulo = new MdlAlmacenArticulo();
        ArrayList<AlmacenArticulo> almacenArticulos;

        if(cnx == null){
            this.cnx.abrirConexion();
            almacenArticulos = mdlAlmacenArticulo.getAlmacenArticulos_articulo(idArticulo, this.cnx);
            for (AlmacenArticulo almacenArticulo : almacenArticulos) {
                int idAlmacen = almacenArticulo.getAlmacen().getIdAlmacen();
                almacenArticulo.setAlmacen(mdlAlmacen.get(idAlmacen, this.cnx));
                
            }
            this.cnx.cerrarConexion();
        }else{
            almacenArticulos = mdlAlmacenArticulo.getAlmacenArticulos_articulo(idArticulo, cnx);
            for (AlmacenArticulo almacenArticulo : almacenArticulos) {
                int idAlmacen = almacenArticulo.getAlmacen().getIdAlmacen();
                almacenArticulo.setAlmacen(mdlAlmacen.get(idAlmacen, cnx));
            }
        }
        
        return almacenArticulos;
    }
    /**
     * 
     * @param idAlmacen
     * @param cnx
     * @return AlmacenArticulo, para obtener los stocks en un almacén determinado
     * @throws ClassNotFoundException
     * @throws SQLException 
     */
    public ArrayList<AlmacenArticulo> getStocks_almacen(int idAlmacen, Conexion cnx) throws ClassNotFoundException, SQLException{
        MdlAlmacenArticulo mdlAlmacenArticulo = new MdlAlmacenArticulo();
        ArrayList<AlmacenArticulo> almacenArticulos;
        
        if (cnx == null) {
            this.cnx.abrirConexion();
            almacenArticulos = mdlAlmacenArticulo.getAlmacenArticulos_almacen(idAlmacen, this.cnx);
            for(AlmacenArticulo almacenArticulo : almacenArticulos){
                int idArticulo = almacenArticulo.getArticulo().getIdArticulo();
                System.out.println("Id: " + idArticulo);
                almacenArticulo.setArticulo(this.mdlArticulo.get(idArticulo, this.cnx));
            }
            this.cnx.cerrarConexion();
        }else{
            almacenArticulos = mdlAlmacenArticulo.getAlmacenArticulos_almacen(idAlmacen, cnx);
            for(AlmacenArticulo almacenArticulo : almacenArticulos){
                int idArticulo = almacenArticulo.getArticulo().getIdArticulo();
                almacenArticulo.setArticulo(this.mdlArticulo.get(idArticulo, cnx));
            }
        }
        
        return almacenArticulos;
    }
    
    public int getArticuloStock(int idArticulo, int idAlmacen, Conexion cnx) throws ClassNotFoundException, SQLException{
        int stock;
        MdlAlmacenArticulo mdlAlmacenArticulo = new MdlAlmacenArticulo();
        AlmacenArticulo almacenArticulo;
        if (cnx == null) {
            this.cnx.abrirConexion();
            int id = mdlAlmacenArticulo.getId(idAlmacen, idArticulo, this.cnx);
            almacenArticulo = mdlAlmacenArticulo.get(id, this.cnx);
            stock = almacenArticulo.getStock();
            this.cnx.cerrarConexion();
        }else{
            int id = mdlAlmacenArticulo.getId(idAlmacen, idArticulo, cnx);
            almacenArticulo = mdlAlmacenArticulo.get(id, cnx);
            stock = almacenArticulo.getStock();
        }
        return stock;
    }
}
